/*
 * $RCSfile: AgentAction.java,v $
 * $Revision: 1.1 $
 * $Date: 2014-03-25 $
 *
 * Copyright (C) 2005 Skin, Inc. All rights reserved.
 *
 * This software is the proprietary information of Skin, Inc.
 * Use is subject to license terms.
 */
package com.skin.demon.agent.servlet;

import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.skin.demon.PackageInfo;
import com.skin.demon.ClassScanner;
import com.skin.demon.MethodInfo;

/**
 * <p>Title: AgentServlet</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2006</p>
 * @author xuesong.net
 * @version 1.0
 */
public class AgentServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @param request
     * @param response
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        String action = request.getParameter("action");

        if(action == null) {
            return;
        }

        if(action.equals("list")) {
            this.list(request, response);
        }
        else if(action.equals("detail")) {
            String packageName = this.getTrimString(request, "packageName");
            String className = this.getTrimString(request, "className");

            if(packageName.length() > 0) {
                this.getPackageDetail(request, response);
            }
            else if(className.length() > 0) {
                this.getClassDetail(request, response);
            }
        }
    }

    /**
     * @param request
     * @param response
     * @throws IOException
     * @throws ServletException
     */
    public void list(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        String packageName = this.getTrimString(request, "packageName");
        List<PackageInfo> childs = new ClassScanner().getChildList(packageName);
        StringBuilder buffer = new StringBuilder();

        for(PackageInfo classInfo : childs) {
            if(classInfo.getPackage()) {
                buffer.append("package=");
                buffer.append(classInfo.getPackageName());
                buffer.append(".");
                buffer.append(classInfo.getName());
                buffer.append("\r\n");
            }
            else {
                buffer.append("class=");
                buffer.append(classInfo.getPackageName());
                buffer.append(".");
                buffer.append(classInfo.getName());
                buffer.append("\r\n");
            }
        }
        this.write(request, response, "text/plain; charset=utf-8", buffer.toString());
    }

    /**
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void getPackageDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String packageName = this.getTrimString(request, "packageName");
        ClassScanner scanner = new ClassScanner();
        List<String> locations = scanner.getLocations(packageName.replace('.', '/'));
        String content = this.join(locations, "\r\n");
        this.write(request, response, "text/plain; charset=utf-8", content);
    }

    /**
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void getClassDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String className = this.getTrimString(request, "className");
        ClassScanner scanner = new ClassScanner();

        String location = scanner.getLocation(className);
        List<String> locations = scanner.getLocations(className.replace('.', '/') + ".class");
        List<MethodInfo> methodInfoList = scanner.getMethodInfoList(className);
        StringBuilder buffer = new StringBuilder();
        buffer.append("name=");
        buffer.append(className);
        buffer.append("\r\n");
        buffer.append("location=");
        buffer.append(location);
        buffer.append("\r\n");
        buffer.append("locations=");
        buffer.append(this.join(locations, ","));
        buffer.append("\r\n");

        /**
         * 此处不做URL encode, 没有必要
         */
        for(MethodInfo methodInfo : methodInfoList) {
            buffer.append("method=");
            buffer.append("name=");
            buffer.append(methodInfo.getMethodName());
            buffer.append("&modifiers=");
            buffer.append(methodInfo.getModifiers());
            buffer.append("&parameterTypes=");
            buffer.append(this.join(methodInfo.getParameterTypes(), ","));
            buffer.append("&returnType=");
            buffer.append(methodInfo.getReturnType());
            buffer.append("&signature=");
            buffer.append(methodInfo.getSignature());
            buffer.append("&description=");
            buffer.append(methodInfo.getDescription());
            buffer.append("\r\n");
        }
        this.write(request, response, "text/plain; charset=utf-8", buffer.toString());
    }

    /**
     * @param request
     * @param name
     * @return String
     */
    public String getTrimString(HttpServletRequest request, String name) {
        String value = request.getParameter(name);
        return (value != null ? value.trim() : "");
    }

    /**
     * @param request
     * @return String
     */
    public String getContextPath(HttpServletRequest request) {
        String contextPath = request.getContextPath();

        if(contextPath == null || contextPath.equals("/")) {
            return "";
        }
        return contextPath;
    }

    /**
     * @param list
     * @param token
     * @return String
     */
    private String join(List<String> list, String token) {
        StringBuilder buffer = new StringBuilder();

        if(list != null && list.size() > 0) {
            int length = list.size() - 1;

            for(int i = 0; i < length; i++) {
                buffer.append(list.get(i)).append(token);
            }

            if(length < list.size()) {
                buffer.append(list.get(length));
            }
        }
        return buffer.toString();
    }

    /**
     * @param request
     * @param response
     * @param contentType
     * @param content
     * @throws IOException
     */
    public void write(HttpServletRequest request, HttpServletResponse response, String contentType, String content) throws IOException {
        byte[] buffer = content.getBytes("UTF-8");
        response.setContentType(contentType);
        response.setContentLength(buffer.length);
        OutputStream outputStream = response.getOutputStream();
        outputStream.write(buffer);
        outputStream.flush();
    }
}
